﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;

namespace Glucometer.ModuleHandler
{

    public delegate void d_EmptyArgument();

    public abstract class GlucometerModuleHandler
    {
        public static event d_EmptyArgument DeviceAutoEnding;

        public static event d_EmptyArgument DeviceEnding;

        public static event d_EmptyArgument DeviceStarting;

        protected static IHarware _hardware;

        protected static DeviceStatus _deviceStatus;

        protected static DeviceSettings _settings;

        protected static Timer _idleTimeCounterTimer = new Timer();

        protected static DeviceMemory _deviceMemory;

        protected static ErrorCode _lastError = ErrorCode.NONE;

        protected static string _lastErrorMessage = "";

        public static int IDLE_TIME_INTERVAL = 10 * 1000;

        public GlucometerModuleHandler(IHarware hardware, DeviceMemory memory, DeviceSettings setting, DeviceStatus status)
        {
            _deviceMemory = memory;

            _settings = setting;

            _deviceStatus = status;
            
            GlucometerModuleHandler._hardware = hardware;
           
        }

        public static void InitializeIdleTimerCounter()
        {
            _idleTimeCounterTimer.Elapsed += new ElapsedEventHandler(_idleTimeCounterTimer_Elapsed);
        }

        static void _idleTimeCounterTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine("IDLE TIMER COUNTER EXPIRED");
            //RAISE THE AUTO ENDING EVENT
            if(DeviceAutoEnding != null)
                DeviceAutoEnding();

            //END THE DEVICE
            endDevice(EndingType.VOLUNTARY, OperationMode.NONE);
        }

        public static void playBeep(BeeperStyle beep)
        {
            Beeper.playBeep(beep);
        }

        protected static void setIdleTimerInterval(double interval)
        {
            GlucometerModuleHandler._idleTimeCounterTimer.Interval = interval;
        }

        protected static void restartIdlePeriodCounter(double interval)
        {            
            _idleTimeCounterTimer.Stop();

            if (interval >= 0)
                setIdleTimerInterval(interval);

            _idleTimeCounterTimer.Start();
        }

        protected static void stopIdlePeriodCounter()
        {
            _idleTimeCounterTimer.Stop();
        }

        public static void endDevice(EndingType endingtype, OperationMode mode)
        {
            //WE DONT NEED TO HANDLE FOR AUTO ENDING BECAUSE THE AUTO ENDING HAPPENS IF THE IDLE TIMER ELAPSES INTERVAL SET
            if (endingtype == EndingType.VOLUNTARY)
            {
                //STOP THE IDLE TIMER COUNTER OTHERWISE IT WILL AGAIN TRY TO TURN OFF THE DEVICE
                _idleTimeCounterTimer.Stop();
                //RAISE THE DEVICE ENDING EVENT
                if(DeviceEnding != null)
                    DeviceEnding();
                _deviceStatus.PoweredOff = true;
                _deviceStatus.IsWaitingForEnding = false;
                playBeep(BeeperStyle.LONG_BEEP);
            }
            else if (endingtype == EndingType.ERROR)
            {
                //IF THE DEVICE IS NOT WAITING FOR ENDING THEN FOLLOW THE ENDING PROCEDURE OF ERROR ENDING
                if (!_deviceStatus.IsWaitingForEnding)
                {
                    //GIVE ERROR BEEP
                    playBeep(BeeperStyle.SHORT_LONG_BEEP);
                    //DISPLAY ERROR SYMBOL
                    _hardware.ShowMode(DisplayComponent.DEVICE_MODE_ERROR);
                    //DISPLAY ERROR CODE
                    _hardware.DisplayErrorCode(ErrorCodeResolver.GetErrorCode(_lastError, mode));
                    //DISPLAY ERROR MESSAGE
                    _hardware.ShowDisplay(_lastErrorMessage);
                    //SET THE DEVICE STATUS TO WAITING FOR ENDING
                    GlucometerModuleHandler._deviceStatus.IsWaitingForEnding = true;
                    //WAIT FOR 30 SEC TO END
                    //THE TIMER IS STARTED WHICH WILL INVOKE VOLUNTARY ENDING UPON EXPIRY
                    restartIdlePeriodCounter(IDLE_TIME_INTERVAL);
                }
            }
        }

        public static void startDevice()
        {
            if (DeviceStarting != null)
                DeviceStarting();
        }

        public static bool Initialization()
        {
            return true;
        }

        public static OperationMode checkModeSelectionProcess(SoftwareEventsType set)
        {
            // TURNING ON TESTING MODE
            if (set == SoftwareEventsType.STRIP_INSERTED)
            {
                return OperationMode.TESTING;
            }
            // TURNING ON BROWSING MODE
            else if (set == SoftwareEventsType.LONG_CLICK)
            {
                return OperationMode.BROWSING;
            }
            //TURNING ON SETUP MODE
            else if (set == SoftwareEventsType.DOUBLE_CLICK)
            {
                return OperationMode.SETUP;
            }
            //TURNING UPLOADING MODE
            else if (set == SoftwareEventsType.USB_INSERTED)
            {
                return OperationMode.UPLOADING;
            }
            
            //THIS EVENT CANNOT SELECT ANY MODE SO RETURN NONE
            return OperationMode.NONE;
        }

        public virtual bool doInitialization(SoftwareEventsType set)
        {
            return true;
        }

        public virtual bool doStatusCheck(SoftwareEventsType set)
        {
            return true;
        }

        public virtual bool doModeValidation(SoftwareEventsType set)
        {
            return true;
        }

        public void startDeviceMode()
        {
            //AFTER LOADING THE MODE START THE IDLE PERIOD COUNTER TIMER            
            _idleTimeCounterTimer.Interval = IDLE_TIME_INTERVAL;
            _idleTimeCounterTimer.AutoReset = false;
            _idleTimeCounterTimer.Start();

            loadMode();
        }

        public virtual void loadMode()
        { }

        public void handleEvent(SoftwareEventsType set)
        {
            if (_deviceStatus.IsWaitingForEnding)
            {
                //IF WAITING FOR ENDING THEN DO NOTHING AND RETURN
                return;
            }

            _lastError = ErrorCode.NONE;
            _lastErrorMessage = string.Empty;
            //HERE HANDLE THE EVENTS THAT ARE COMMON TO EACH MODULE            

            //THIS CALL WILL MAKE SPECIFIC MODULE HANDLER TO HANDLE THE EVENT
            //IF THE EVENT WAS VALID IN THE MODE THEN IT WILL RETURN TRUE WHICH WILL
            //RESET THE AUTO ENDING TIMER OTHERWISE THE TIMER CONTINUES TO RUN
            if (handleEventInMode(set))
            {
                //IF THE DEVICE IS NOT POWERED OFF THEN RESTART THE IDLE TIME TIMER
                if (!_deviceStatus.PoweredOff)
                    restartIdlePeriodCounter(_idleTimeCounterTimer.Interval);
            }
            else
            {
                playBeep(BeeperStyle.DOUBLE_BEEP);
            }
        }

        public abstract bool handleEventInMode(SoftwareEventsType set);

        protected static void setLastError(ErrorCode errorCode, string message)
        {
            _lastError = errorCode;
            _lastErrorMessage = message;
        }

        internal static void PersistState(double Batterylife)
        {
            XMLFileDumper.SaveState(_deviceMemory, _settings, Batterylife);
        }

        internal static void LoadState(DeviceSettings setting, DeviceMemory memory)
        {
            DeviceSettings oldSetting = XMLFileDumper.GetSettingsFromXMLFile();
            if (oldSetting != null)
                oldSetting = setting;
            XMLFileDumper.GetDeviceMemoryFromXMLFile(memory);
        }
    }
}